/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO;

import static DAO.AbstractDAO.fermeturesSilencieuses;
import static DAO.AbstractDAO.initialisationRequetePreparee;
import Modele.Incident;
import Modele.Technicien;
import Utils.Constantes;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 *
 * @author 20cent
 */
public class IncidentDAOmysql extends AbstractDAO implements IncidentDao{
    
    private static final String SQL_INSERT = "INSERT INTO `nemo_velo`.`" + ChampsBDD.TABLE_INCIDENT + "` (`"
            + ChampsBDD.INCIDENT_ID + "`, `"
            + ChampsBDD.VELO_ID + "`, `"
            + ChampsBDD.TYPE_INC_ID + "`, `"
            + ChampsBDD.INCIDENT_STATUT + "`, `"
            + ChampsBDD.INCIDENT_PRIORITE + "`, `"
            + ChampsBDD.INCIDENT_COMMENTAIRE
            + "`) VALUES (NULL, ?, ?, ?, ?, ?);";
    private static final String SQL_UPDATE = "UPDATE `nemo_velo`.`" + ChampsBDD.TABLE_INCIDENT + "` SET `"
            + ChampsBDD.TYPE_INC_ID + "` = ? ,`"
            + ChampsBDD.TECHNICIEN_ID + "` = ? ,`"
            + ChampsBDD.INCIDENT_DATE_FERMETURE + "` = ? ,`"
            + ChampsBDD.INCIDENT_STATUT + "` = ? ,`"
            + ChampsBDD.INCIDENT_PRIORITE + "` = ? ,`"
            + ChampsBDD.INCIDENT_COMMENTAIRE + "` = ? "
            + "WHERE `" + ChampsBDD.INCIDENT_ID + "` = ?;";
    private static final String SQL_SELECT_PAR_ID = "SELECT * "
            + "FROM  `" + ChampsBDD.TABLE_INCIDENT + "` i LEFT OUTER JOIN "
            + "`" + ChampsBDD.TABLE_UTILISATEUR + "` u ON i.`" + ChampsBDD.TECHNICIEN_ID + "` = u.`" + ChampsBDD.UTILISATEUR_ID 
            + "` INNER JOIN `" + ChampsBDD.TABLE_TYPE_INCIDENT + "` t ON i.`" + ChampsBDD.TYPE_INC_ID + "` = t.`" + ChampsBDD.TYPE_INC_ID
            + "` INNER JOIN `" + ChampsBDD.TABLE_VELO + "` v ON i.`" + ChampsBDD.VELO_ID + "` = v. `" + ChampsBDD.VELO_ID + "` "
            + "WHERE  `" + ChampsBDD.INCIDENT_ID + "` = ?";
    private static final String SQL_SELECT_FILTER = "SELECT * "
            + "FROM  `" + ChampsBDD.TABLE_INCIDENT + "` i LEFT OUTER JOIN "
            + "`" + ChampsBDD.TABLE_UTILISATEUR + "` u ON i.`" + ChampsBDD.TECHNICIEN_ID + "` = u.`" + ChampsBDD.UTILISATEUR_ID 
            + "` INNER JOIN `" + ChampsBDD.TABLE_TYPE_INCIDENT + "` t ON i.`" + ChampsBDD.TYPE_INC_ID + "` = t.`" + ChampsBDD.TYPE_INC_ID
            + "` INNER JOIN `" + ChampsBDD.TABLE_VELO + "` v ON i.`" + ChampsBDD.VELO_ID + "` = v. `" + ChampsBDD.VELO_ID + "` ";
    private static final String WHERE = "WHERE ";
    private static final String AND = "AND ";
    private static final String EQ = " = ";
    private static final String QUOTE = "'";
    private static final String TIQ = "`";

    public IncidentDAOmysql(DAOFactory daoFactory) {
        super(daoFactory);
    }

    @Override
    public void save(Incident incident, int velo_id, int typeinc_id) throws DAOException {
        Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet valeursAutoGenerees = null;

        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
            preparedStatement = initialisationRequetePreparee(connexion, SQL_INSERT, true, 
                                                                                velo_id, 
                                                                                typeinc_id,
                                                                                incident.getMStatut(),
                                                                                incident.getIncidentProrite(),
                                                                                incident.getIncidentCommentaire());
            int statut = preparedStatement.executeUpdate();
            /* Analyse du statut retourné par la requête d'insertion */
            if (statut == 0) {
                throw new DAOException("Échec de la création de l'incident, aucune ligne ajoutée dans la table.");
            }
            /* Récupération de l'id auto-généré par la requête d'insertion */
            valeursAutoGenerees = preparedStatement.getGeneratedKeys();
            if (valeursAutoGenerees.next()) {
                /* Puis initialisation de la propriété id du bean Utilisateur avec sa valeur */
                incident.setMId(valeursAutoGenerees.getInt(1));
            } else {
                throw new DAOException("Échec de la création de l'incident en base, aucun ID auto-généré retourné.");
            }
        } catch (SQLException e) {
            throw new DAOException(e);
        } finally {
            fermeturesSilencieuses(valeursAutoGenerees, preparedStatement, connexion);
        }
    }

    @Override
    public void update(Incident incident, int typeinc_id, int technicien_id) throws DAOException {
        Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet valeursAutoGenerees = null;

        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
            preparedStatement = initialisationRequetePreparee(connexion, SQL_UPDATE, false,  
                                                                                typeinc_id, 
                                                                                technicien_id,
                                                                                incident.getMDateFermeture(), 
                                                                                incident.getMStatut(), 
                                                                                incident.getIncidentProrite(), 
                                                                                incident.getIncidentCommentaire(),
                                                                                incident.getMId());
            int statut = preparedStatement.executeUpdate();
            /* Analyse du statut retourné par la requête d'insertion */
            if (statut == 0) {
                throw new DAOException("Échec de la création du type d'incident, aucune ligne ajoutée dans la table.");
            }

        } catch (SQLException e) {
            throw new DAOException(e);
        } finally {
            fermeturesSilencieuses(valeursAutoGenerees, preparedStatement, connexion);
        }
    }

    @Override
    public Incident getByID(int id) throws DAOException {
        Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Incident incident = null;

        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
            preparedStatement = initialisationRequetePreparee(connexion, SQL_SELECT_PAR_ID, false, id);
            resultSet = preparedStatement.executeQuery();
            /* Parcours de la ligne de données de l'éventuel ResulSet retourné */
            if (resultSet.next()) {
                incident = map(resultSet);
            }
        } catch (Exception e) {
            throw new DAOException(e);
        } finally {
            fermeturesSilencieuses(resultSet, preparedStatement, connexion);
        }
        return incident;
    }

    @Override
    public ArrayList<Incident> getByFilter(String[] champs, String[] valeurs) throws DAOException {
        Connection connexion = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        ArrayList<Incident> liste = new ArrayList<>();
        
        //Construction de la requête
        StringBuilder builder = new StringBuilder(SQL_SELECT_FILTER);
        if(champs != null && valeurs != null && champs.length > 0 && valeurs.length > 0 && champs.length == valeurs.length){
            builder.append(WHERE);
            for(int i = 0; i < champs.length ; i++){
                if(i != 0){
                    builder.append(AND);
                }
                builder.append(TIQ).append(champs[i]).append(TIQ)
                        .append(EQ)
                        .append(QUOTE).append(valeurs[i]).append(QUOTE);
            }
        }

        try {
            /* Récupération d'une connexion depuis la Factory */
            connexion = daoFactory.getConnection();
            preparedStatement = initialisationRequetePreparee(connexion, builder.toString(), false);
            resultSet = preparedStatement.executeQuery();
            /* Parcours de la ligne de données de l'éventuel ResulSet retourné */
            while (resultSet.next()) {
                liste.add(map(resultSet));
            }
        } catch (Exception e) {
            throw new DAOException(e);
        } finally {
            fermeturesSilencieuses(resultSet, preparedStatement, connexion);
        }
        return liste;
    }
    
    private static Incident map(ResultSet resultSet) throws SQLException {
        Incident incident = new Incident();

        incident.setMId(resultSet.getInt(ChampsBDD.INCIDENT_ID));
        incident.setMDateOuverture(resultSet.getDate(ChampsBDD.INCIDENT_DATE_OUVERTURE));
        incident.setMDateFermeture(resultSet.getDate(ChampsBDD.INCIDENT_DATE_FERMETURE));
        incident.setMStatut(resultSet.getString(ChampsBDD.INCIDENT_STATUT));
        incident.setIncidentProrite(resultSet.getString(ChampsBDD.INCIDENT_PRIORITE));
        incident.setIncidentCommentaire(resultSet.getString(ChampsBDD.INCIDENT_COMMENTAIRE));
        //création du vélo
        incident.setmVelo(VeloDAOmysql.map(resultSet));
        //création du type incident
        incident.setmTypInc(TypeIncidentDAOmysql.map(resultSet));
        //création du technicien s'il a été assigné
        if(resultSet.getInt(ChampsBDD.TECHNICIEN_ID) != 0){
            incident.setmTechnicien((Technicien)UtilisateurDAOmysql.map(resultSet));
        }

        return incident;
    }
}
